/*
 * DataQueue.h
 *
 *  Created on: 2013-9-5
 *      Author: root
 */

#ifndef DATAQUEUE_H_
#define DATAQUEUE_H_

#include <zmq.h>
//boost thread对push_options有严重错误，改为修改gcc编译选项
//增加 -isystem ${ProjDirPath}/../../others 表示将others目录下的内容作为系统库的头文件
//#pragma GCC push_options
//#pragma GCC diagnostic ignored "-Wconversion"
#include <boost/scoped_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/cstdint.hpp>
//#pragma GCC pop_options
#include <string>
#include <vector>
using namespace std;

namespace core {
namespace zmq {

//接受消息的队列线程,必须派生使用
/* 已知问题
 1 epoll的thread线程会阻塞thread.cpp:98
 2 DataRecvThread 无法正常退出
对应处理：
必须使用 new 构造派生的子类，并且不要使用delete,同名的队列实例，系统开始退出只使用一次,让进程退出清理资源
 */
class DataRecvThread {
public:
	DataRecvThread();
	DataRecvThread(std::string queueName, int highWater = 100000, int mode = ZMQ_PULL);
	virtual ~DataRecvThread();

	int Init(std::string queueName, int highWater, int mode);

	//仅提供启动，初始化相关资源，类销毁是释放资源
	//如果多次使用，多次构造这个类即可
	bool Start();
	//void Stop();
	void operator()();

	void WaitForDone();
protected:
	//真正的干活的地方,收到一个信息调用处理1次,必须重载，并调用recv** 接收内容
	virtual void oneWork() = 0;

	void recvC(const boost::uint8_t &c);
	void recvS(const boost::uint16_t &s);
	void recvI(const boost::int32_t &i);
	void recvL(const boost::int64_t &l);

	void recv(string &str);
	//void recvV(vector<std::string> &array);
	size_t recvBuf(void *buf_, size_t len_, int flags_ = 0);

	bool runing;
protected:
	//C++ 的这个有些奇怪，销毁时会 Block
	//使用C的接口有好转，仍然会出现2种情况[少了一些]： 1，Block 2,zmq_assert退出
	///others/original/zeromq3_csbit.tar.gz 这个是修改zeromq-3.2.3.tar.gz的消除以上2个问题的
	string queueName;
	void* ctx;
	void* sock;
	boost::thread thrPull;

#define MAX_TEXT  65536 //和common/libDbProtocol解析的串最大长度一致，防止少收数据
	char buf[MAX_TEXT];
	bool isExist;
};

//发送消息
class DataSend {
public:
	DataSend();
	DataSend(std::string queueName, int highWater = 10000, int mode = ZMQ_PUSH);
	virtual ~DataSend();

	//ZMQ_DONTWAIT表示1个完整的消息，消息包含的结构都是ZMQ_SNDMORE发送
	void sendC(const boost::uint8_t &c, int flag = ZMQ_SNDMORE);
	void sendS(const boost::uint16_t &i, int flag = ZMQ_SNDMORE);
	void sendI(const boost::int32_t &i, int flag = ZMQ_SNDMORE);
	void sendL(const boost::int64_t &i, int flag = ZMQ_SNDMORE);
	void send(const string &str, char flag = ZMQ_SNDMORE);
	//发送数组必须在1个消息的中间完成[ZMQ_DONTWAIT前]
	//void sendV(const vector<std::string> &array, char flag = ZMQ_SNDMORE);
	//
	void sendBuf(const void *buf, unsigned long len, int flags = ZMQ_SNDMORE);

public:
	//处理序列化和ZMQ的发送
	void* ctx;
	void* sock;
	string queueName;

	bool isDrop;
};

} /* namespace base */
} /* namespace common */
#endif /* DATAQUEUE_H_ */
